package alpha.com.google.code.mechanic.janitor.ui;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import alpha.com.google.code.mechanic.janitor.controller.ContextData;
import alpha.com.google.code.mechanic.janitor.model.DefaultSysFilePath;
import alpha.com.google.code.mechanic.janitor.model.ProjectContext;

import com.google.eclipse.mechanic.internal.TaskType;

/**
 * 
 * The class is to let the users indicate the information related to the Task
 * and the Context where the new preferences will be saved to.
 *
 * Last_edited: Nov 6, 2014
 *
 * @History
 * 1. Change the method used to save the Contexts information to context.con
 * file.
 * @author jingjiejiang
 * @edited Nov 3, 2014
 * 1) In the method addNewCtxToList(), use the method SaveContextsInfo() of
 * ContextData to replace the method serializeContextsInfo(File file) of
 * ContextsCollector
 * 
 * 2) change the parameters of method addNewCtxToFile from (String name,
 * String location, File file) to (String name, String location)
 * 
 * 2. Delete the private field: String defHomePath
 * @author jingjiejiang
 * @edited Nov 6, 2014
 * 
 * @author jingjiejiang
 * @since Oct 5, 2014
 */
public class NewTaskWizardPage extends WizardPage {
  
  private Text txtTaskTitle;
  private Text txtTaskDesc;
  private Text txtNewContext;
  private Text txtTaskFileId;
  
  private Combo comboTaskType;
  private Button btnSaveToCurCtx;
  private Button btnSaveToNewCtx;
  private Combo comboCurContext;
  
  // The field indicates whether save the new preferences to a new Context.
  private boolean isSaveToNewCtx = false;
  
  private ContextData contextData = new ContextData();
  private List<String> listCtxNames = new ArrayList<String>();
  
  // private String defHomePath;
  private String defCtxParentPath;

  /**
   * Create the wizard.
   */
  public NewTaskWizardPage() {
    super("wizardPage");
    setTitle("Preference Recorder Output");
    setDescription("Save new preferences.");
    
    try {
      initCtxNameList();
    } catch (Exception e) {
      MessageDialog.openError(getShell(), "Couldn't read the Context data."
          , e.getMessage());
    }
    
    initDefSysPaths();
  }
  
  @Override
  public boolean canFlipToNextPage() {
    
    return false;
  }
  
  public String getTaskTitle() {
    return txtTaskTitle.getText();
  }
  
  public String getTaskDesc() {
    return txtTaskDesc.getText();
  }
  
  public TaskType getTaskType() {
    
    return TaskType.values()[comboTaskType.getSelectionIndex()];
  }

  public String getTxtTaskFileId() {
    
    return txtTaskFileId.getText();
  }
  
  public String getNewCtxName() {
    return txtNewContext.getText();
  }
  
  public String getCurCtxName() {
    return comboCurContext.getText();
  }

  public boolean isSaveToNewCtx() {
    return isSaveToNewCtx;
  }
  
  private void initCtxNameList() throws Exception {
   
    try {
      contextData.readContextsFile();
    } catch (Exception error) {
      throw error;
    }
    
    listCtxNames = contextData.getContextsCollector().getCtxNameList();
  }
  
  private void initDefSysPaths() {
    
    DefaultSysFilePath syspath = new DefaultSysFilePath();
    syspath.initDefSysFilePath();
    
    //defHomePath = syspath.getDefaultSysFilePath();
    syspath.initCtxFileDir();
    defCtxParentPath = syspath.getDefaultSysFilePath();
  }

  /**
   * Create contents of the wizard.
   * @param parent
   */
  public void createControl(Composite parent) {
    Composite container = new Composite(parent, SWT.NULL);

    setControl(container);
    
    Label lblTaskTitle = new Label(container, SWT.NONE);
    lblTaskTitle.setAlignment(SWT.RIGHT);
    lblTaskTitle.setBounds(10, 35, 74, 16);
    lblTaskTitle.setText("Title:");
    
    initTextTaskTitle(container);
    
    Label lblTaskDesc = new Label(container, SWT.NONE);
    lblTaskDesc.setAlignment(SWT.RIGHT);
    lblTaskDesc.setBounds(10, 63, 74, 14);
    lblTaskDesc.setText("Description:");
    
    initTextTaskDesc(container);
    
    Label lblTaskType = new Label(container, SWT.NONE);
    lblTaskType.setAlignment(SWT.RIGHT);
    lblTaskType.setBounds(10, 91, 74, 14);
    lblTaskType.setText("Type:");
    
    initComboTaskType(container);
    
    Label label = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
    label.setBounds(0, 150, 590, 2);
    
    initBtnSaveToCurCtx(container);
    
    Label lblNewLabel_2 = new Label(container, SWT.NONE);
    lblNewLabel_2.setBounds(10, 10, 133, 14);
    lblNewLabel_2.setText("New Task information:");
    
    Label lblNewLabel_3 = new Label(container, SWT.NONE);
    lblNewLabel_3.setBounds(10, 161, 63, 16);
    lblNewLabel_3.setText("Context:");
    
    initComboCurContext(container);
    initBtnSaveToNewCtx(container);
    initTextNewCtx(container);
    
    Label lblNewLabel_4 = new Label(container, SWT.NONE);
    lblNewLabel_4.setBounds(40, 211, 94, 14);
    lblNewLabel_4.setText("Select a Context:");
    
    Label lblNewContextName = new Label(container, SWT.NONE);
    lblNewContextName.setText("Name:");
    lblNewContextName.setBounds(40, 258, 46, 14);
    
    Label lblTaskFileId = new Label(container, SWT.NONE);
    lblTaskFileId.setAlignment(SWT.RIGHT);
    lblTaskFileId.setBounds(10, 121, 74, 14);
    lblTaskFileId.setText("Task file ID:");
   
    initTestTaskFileId(container);
    
    Label lblNewLabel = new Label(container, SWT.NONE);
    lblNewLabel.setBounds(324, 119, 31, 14);
    lblNewLabel.setText(".epf");
  }
  
  private void initTextTaskTitle (Composite composite) {
    
    txtTaskTitle = new Text(composite, SWT.BORDER);
    txtTaskTitle.addModifyListener(new ModifyListener() {
      public void modifyText(ModifyEvent e) {
        
        updateWizardButtons();
      }
    });
    txtTaskTitle.setBounds(90, 32, 490, 19);
  }
  
  private void initTextTaskDesc (Composite composite) {
    
    txtTaskDesc = new Text(composite, SWT.BORDER);
    txtTaskDesc.addModifyListener(new ModifyListener() {
      public void modifyText(ModifyEvent e) {
        
        updateWizardButtons();
      }
    });
    txtTaskDesc.setBounds(90, 60, 490, 19);
  }
  
  private void initComboTaskType (Composite composite) {
    
    comboTaskType = new Combo(composite, SWT.NONE);
    comboTaskType.setBounds(90, 87, 125, 22);
    comboTaskType.setItems(new String[] {"Last Mod", "Reconcile"});
    comboTaskType.select(0);
  }

  private void initBtnSaveToCurCtx (Composite composite) {
    
    btnSaveToCurCtx = new Button(composite, SWT.RADIO);
    btnSaveToCurCtx.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        
        isSaveToNewCtx = false;
        
        btnSaveToCurCtx.setSelection(true);
        comboCurContext.setEnabled(true);
        comboCurContext.setBackground(new Color(null, 255, 255, 255));
        setComboCurCtxItems();
        
        btnSaveToNewCtx.setSelection(false);
        txtNewContext.setText("");
        txtNewContext.setBackground(new Color(null, 204, 205, 207));
        txtNewContext.setEditable(false);
        
        updateWizardButtons();
      }
    });
    btnSaveToCurCtx.setBounds(10, 183, 178, 18);
    btnSaveToCurCtx.setText("Save to an existing Context:");
    btnSaveToCurCtx.setSelection(true);
  }
  
  private void initComboCurContext (Composite composite) {
    
    comboCurContext = new Combo(composite, SWT.NONE);
    comboCurContext.setBounds(140, 207, 243, 22);
    setComboCurCtxItems();
  }
  
  private void setComboCurCtxItems () {
    
    comboCurContext.setItems(listCtxNames.toArray(new String[listCtxNames.size()]));
    
    if (listCtxNames.size() != 0) {
      comboCurContext.select(0);
    }
  }
  
  private void initBtnSaveToNewCtx (Composite composite) {
    
    btnSaveToNewCtx = new Button(composite, SWT.RADIO);
    btnSaveToNewCtx.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
      
        isSaveToNewCtx = true;
        
        btnSaveToCurCtx.setSelection(false);
        comboCurContext.clearSelection();
        comboCurContext.setEnabled(false);
        comboCurContext.setBackground(new Color(null, 204, 205, 207));
        comboCurContext.setText("");
        
        btnSaveToNewCtx.setSelection(true);
        txtNewContext.setBackground(new Color(null, 255, 255, 255));
        txtNewContext.setEditable(true);
        
        updateWizardButtons();
      }
    });
    btnSaveToNewCtx.setBounds(10, 231, 157, 18);
    btnSaveToNewCtx.setText("Saved to a new Context:");
    btnSaveToNewCtx.setSelection(false);
  }
  
  private void initTextNewCtx (Composite composite) {
    
    txtNewContext = new Text(composite, SWT.BORDER);
    txtNewContext.addModifyListener(new ModifyListener() {
      public void modifyText(ModifyEvent e) {
        
        // Check whether the Context has the same name.
        String newname = txtNewContext.getText();
        if (false == contextData.getContextsCollector().isValidCtxName(newname)){
          MessageDialog.openError(getShell(), "Error", "There already exist a"
              + " Context with the same name. Please specify another name for"
              + " the new Context.");  
          
          return;
        }
        else{
          updateWizardButtons();
        }
      }
    });
    txtNewContext.setEditable(false);
    txtNewContext.setBounds(90, 255, 297, 19);
    txtNewContext.setBackground(new Color(null, 204, 205, 207));
  }
  
  private void initTestTaskFileId(Composite composite) {
    
    txtTaskFileId = new Text(composite, SWT.BORDER);
    txtTaskFileId.addModifyListener(new ModifyListener() {
      public void modifyText(ModifyEvent e) {
       
        // Check duplicated Task file name.
        if (false == isSaveToNewCtx){
          
          String newname = txtTaskFileId.getText() + ".epf";
          File context = new File(defCtxParentPath + comboCurContext.getText());
          File[] ctxfiles = context.listFiles();
          
          for (File file : ctxfiles) {
            
            if (file.getName().equals(newname)) {
              
              MessageDialog.openError(getShell(), "Error", "There already"
                  + " exist a Task file with the same name in the selected"
                  + " Context. Please specify another name for the new Task.");  
              return;
            }
          }
          
          // If the new Task name does not duplicate an existing one, update
          // wizard buttons.
          updateWizardButtons();
        }
        else {
          
          updateWizardButtons();
        }
      }
    });
    txtTaskFileId.setBounds(90, 116, 234, 19);
  }
  
  private void updateWizardButtons() {
    
    getWizard().getContainer().updateButtons();
  }
  
  /**
   * The method is to return the file location of the Context where the new
   * Task should be saved to. If the user chooses to save the Task to a new
   * Context, then generate the file folder for the new Context and then
   * write the change to context.con file. Otherwise, return the file
   * location of the selected Context directly.
   *
   * @return
   * @throws IOException 
   */
  public String getCtxFileLocation() throws IOException {
    
    if (true == isSaveToNewCtx) {
      
      String ctxname = txtNewContext.getText();
      String ctxlocation = defCtxParentPath + ctxname;
      
      boolean success = new File(ctxlocation).mkdirs();
      if (!success) {
        // Directory creation failed
        MessageDialog.openWarning(getShell(),  "Error",
          "The system failed to create a file folder for the Context"
          + " added before.");
        return null;
      }
      else {
        
        try {
          addNewCtxToFile (ctxname, ctxlocation);
        } catch (IOException e) {
          throw e;
        }
            
        return ctxlocation; 
      }        
    }
    else {
      
      String ctxname = comboCurContext.getText(); 
      return contextData.getContextsCollector().getFileLocFromName(ctxname);
    }
  }
  
  /**
   * The method is to add the information of the new Context to the
   * context.con file. 
   *
   * @param name The name of the new Context.
   * @param location The file location of the new Context.
   * @param file The path of the context.con file.
   * @throws IOException 
   *
   */
  private void addNewCtxToFile (String name, String location) throws IOException {
    
    ProjectContext context = new ProjectContext(name, location);
    contextData.getContextsCollector().addContext(context);
    try {
      contextData.saveContextsInfo();
    } catch (IOException e) {
      throw e;
    }
  }

}
